package com.jfinal.util;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.util.Assert;

/**
 * spring 工具类
 * @ClassName: SpringUtils 
 * @author huangx
 * @date 2015年2月4日 上午11:57:58
 */
public class SpringUtils {
	// 容器 每次请求都创建一个实例 
	public static final String SCOPE_PROTOTYPE = "prototype";
	// 容器 唯一实例
	public static final String SCOPE_SINGLETON = "singleton";
	// web 在一次Http请求中，容器会返回该Bean的同一个实例，而对于不同的用户请求，会返回不同的实例。
	public static final String SCOPE_REQUEST = "request";
	// web 在一次回话请求中，容器会返回该Bean的同一个实例，而对于不同的用户请求，会返回不同的实例。
	public static final String SCOPE_SESSION = "session";
	// web 全局的HttpSession中，容器会返回该bean的同一个实例，典型为在是使用portlet context的时候有效
	public static final String SCOPE_GLOBALSESSION = "globalsession";

	/*---------------- FileSystemXmlApplicationContext -------------*/
	/**
	 * @Title: 创建 ApplicationContext
	 * @param configurations
	 * @return FileSystemXmlApplicationContext 
	 */
	public static FileSystemXmlApplicationContext newFileSystemXmlApplicationContextByConfigurations(String... configurations) {
		Assert.notNull(configurations);
		return new FileSystemXmlApplicationContext(configurations);
	}

	/*---------------- AnnotationConfigApplicationContext -------------*/
	/**
	 * @Title: 创建 ApplicationContext
	 * @param basePackages
	 * @return AnnotationConfigApplicationContext 
	 */
	public static AnnotationConfigApplicationContext newAnnotationConfigApplicationContextByBasePackages(String... basePackages) {
		Assert.notNull(basePackages);
		return new AnnotationConfigApplicationContext(basePackages);
	}

	/**
	 * @Title: 创建 ApplicationContext
	 * @param annotatedClasses
	 * @return AnnotationConfigApplicationContext 
	 */
	public static AnnotationConfigApplicationContext newAnnotationConfigApplicationContextByAnnotatedClasses(Class<?>... annotatedClasses) {
		Assert.notNull(annotatedClasses);
		return new AnnotationConfigApplicationContext(annotatedClasses);
	}

	/**
	 * @Title: 创建 ApplicationContext
	 * @param annotatedClasses
	 * @return AnnotationConfigApplicationContext 
	 */
	public static AnnotationConfigApplicationContext newAnnotationConfigApplicationContextByAnnotatedClasses(String... annotatedClasses) {
		return newAnnotationConfigApplicationContextByAnnotatedClasses(ReflectUtils.forNames(annotatedClasses));
	}

	/*---------------- ClassPathXmlApplicationContext -------------*/
	/**
	 * @Title: 创建 ApplicationContext  
	 * @param configLocations
	 * @return ApplicationContext 
	 */
	public static ClassPathXmlApplicationContext newClassPathXmlApplicationContextByConfigLocations(String... configLocations) {
		Assert.notNull(configLocations);
		return new ClassPathXmlApplicationContext(configLocations);
	}

	/**
	 * @Title: 生产 bean builder
	 * @param serviceClass
	 * @return
	 */
	public static BeanDefinitionBuilder genericBean(Class<?> serviceClass) {
		Assert.notNull(serviceClass);
		return BeanDefinitionBuilder.genericBeanDefinition(serviceClass);
	}

	/**
	 * @Title: 生产 bean builder
	 * @param beanClassName
	 * @return
	 */
	public static BeanDefinitionBuilder genericBean(String beanClassName) {
		Assert.notNull(beanClassName);
		return BeanDefinitionBuilder.genericBeanDefinition(beanClassName);
	}

	/**
	 * 向spring容器注册bean
	 * @Title: 
	 * @param beanName
	 * @param beanDefinition
	 * @param context
	 */
	public static void registerBean(ApplicationContext context, String beanName, BeanDefinition beanDefinition) {
		// ApplicationContext 不能为空
		Assert.notNull(context);
		// 断言 bean 没有定义
		Assert.state(!context.containsBean(beanName), "bean [" + beanName + "] is exist.");
		// BeanDefinition 不能为空
		Assert.notNull(beanDefinition);
		// 注册
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) context;
		BeanDefinitionRegistry beanDefinitonRegistry = (BeanDefinitionRegistry) configurableApplicationContext.getBeanFactory();
		beanDefinitonRegistry.registerBeanDefinition(beanName, beanDefinition);
	}
}
